<?php
declare (strict_types=1);

namespace app\controller;

use app\BaseController;
use app\common\Common;
use app\common\Pay;
use app\common\Sms;
use app\common\UserService;
use app\model\Advise;
use app\model\AdviseClass;
use app\model\Config;
use app\model\LineOrders;
use app\model\LineSpot;
use app\model\User;
use app\model\UserBank;
use app\model\UserCollect;
use app\model\UserCoupon;
use app\model\UserLayer;
use app\model\UserMoneyLog;
use app\model\UserWithdraw;
use app\model\Vip;
use app\model\VipOrders;
use app\tool\Random;
use GuzzleHttp\Client;
use thans\jwt\facade\JWTAuth;
use think\db\Query;
use think\Exception;
use think\facade\Db;
use think\facade\Validate;

class UserController extends BaseController
{
	
	function login()
	{
		$logintype = $this->request->post('logintype'); #mobile  password mini
		$mobile = $this->request->post('mobile');
		$password = $this->request->post('password');
		$captcha = $this->request->post('captcha');
		$minicode = $this->request->post('minicode');
		
		switch ($logintype) {
			case 'mobile':
				$user = User::getByMobile($mobile);
				if (!$mobile || !$user) {
					$this->writeJson(0, '该号码未注册');
				}
				$captchaResult = Sms::check($mobile, $captcha, 'login');
				if (!$captchaResult) {
					$this->writeJson(0, '验证码错误');
				}
				break;
			case 'password':
				$user = User::getByMobile($mobile);
				if (!$mobile || !$user) {
					$this->writeJson(0, '该号码未注册');
				}
				if ($user->password != $this->getEncryptPassword($password, $user->salt)) {
					$this->writeJson(0, '密码错误');
				}
				break;
			case 'mini':
				
				try {
					$openid = Common::getWechatOpenid($minicode);
				} catch (\Throwable $e) {
					$this->writeJson(0, $e->getMessage());
				}
				
				$user = User::getByOpenid($openid);
				if (!$user) {
					$this->writeJson(0, '请先注册');
				}
				break;
			default:
				$this->writeJson(0, '登录类型错误');
		}
		if ($user->status != 'normal') {
			$this->writeJson(0, '该账号已被封禁');
		}
		$token = JWTAuth::builder(['user_id' => $user->id]);
		$this->writeJson(1, '登录成功', '', 'json', ['Authorization' => 'Bearer ' . $token]);
	}
	
	#注册
	function register()
	{
		$mobile = $this->request->post('mobile');
		$captcha = $this->request->post('captcha');
		$password = $this->request->post('password');
		$minicode = $this->request->post('minicode');
		$new_invitecode = $this->request->post('new_invitecode');
		
		
		if (empty($minicode) || empty($password) || empty($mobile) || empty($captcha) || empty($new_invitecode)) {
			$this->writeJson(0, '参数错误');
		}
		
		try {
			$openid = Common::getWechatOpenid($minicode);
		} catch (\Throwable $e) {
			$this->writeJson(0, $e->getMessage());
		}
		
		
		// 启动事务
		Db::startTrans();
		try {
			if (User::lock(true)->getByMobile($mobile)) {
				throw new Exception('手机号已存在');
			}
			
			$captchaResult = Sms::check($mobile, $captcha, 'register');
			if (!$captchaResult) {
				throw new Exception('验证码错误');
			}
			
			$parent = User::getByInvitecode($new_invitecode); //父级
			if (!$parent) {
				throw new Exception('邀请码错误');
			}
			
			do {
				$nickname = '用户' . rand(1000000, 9999999);
			} while (User::where(['nickname' => $nickname])->find());
			do {
				$invitecode = Random::alnum();
			} while (User::where(['invitecode' => $invitecode])->find());
			
			$ip = request()->ip();
			$time = time();
			$data = [
				'mobile' => $mobile,
				'level' => 1,
				'score' => 0,
				'avatar' => '/assets/img/avatar.png',
				'openid' => $openid,
				'invitecode' => $invitecode,
				'pid' => $parent->id
			];
			$params = array_merge($data, [
				'nickname' => $nickname,
				'salt' => Random::alnum(),
				'jointime' => $time,
				'joinip' => $ip,
				'logintime' => $time,
				'loginip' => $ip,
				'prevtime' => $time,
				'status' => 'normal',
			]);
			$params['password'] = $this->getEncryptPassword($password, $params['salt']);
			
			$user = User::create($params);
			//增加直推关系
			$position = UserLayer::where('user_id', $parent->id)->select();
			$data['user_id'] = $user->id;
			$data['pid'] = $parent->id;
			$data['level'] = 1;
			UserLayer::create($data);
			if (!$position->isEmpty()) {
				foreach ($position as $v) {
					$data = [
						'user_id' => $user->id,
						'pid' => $v->pid,
						'level' => $v->level + 1,
					];
					UserLayer::create($data);
				}
			}
			//生成token
			$token = JWTAuth::builder(['user_id' => $user->id]);
			// 提交事务
			Db::commit();
		} catch (\Exception $e) {
			// 回滚事务
			Db::rollback();
			$this->writeJson(0, $e->getMessage());
		}
		
		
		$this->writeJson(1, '注册成功', '', 'json', ['Authorization' => 'Bearer ' . $token]);
	}
	
	/**
	 * 重置密码
	 * @return void
	 */
	function resetpwd()
	{
		$mobile = $this->request->post("mobile");
		$newpassword = $this->request->post("newpassword");
		$confirm_password = $this->request->post("confirm_password");
		$captcha = $this->request->post("captcha");
		if (!Validate::is($mobile, 'mobile')) {
			$this->writeJson(0, '手机号格式错误');
		}
		if (!Validate::is($newpassword, '\S{8,30}')) {
			$this->writeJson(0, '密码必须8-30个字符');
		}
		if ($newpassword != $confirm_password) {
			$this->writeJson(0, '确认密码不一致');
		}
		$user = User::getByMobile($mobile);
		if (!$user) {
			$this->writeJson(0, '手机号未注册');
		}
		$ret = Sms::check($mobile, $captcha, 'resetpwd');
		if (!$ret) {
			$this->writeJson(0, '验证码错误');
		}
		Sms::flush($mobile, 'resetpwd');//清空验证码
		$salt = Random::alnum();
		$newpassword = $this->getEncryptPassword($newpassword, $salt);
		$user->password = $newpassword;
		$user->salt = $salt;
		$user->loginfailure = 0;
		$user->save();
		$this->writeJson();
	}
	
	
	/**
	 * 重置|设置交易密码
	 * @return void
	 */
	function resetTradepwd()
	{
		$newpassword = $this->request->post("newpassword");
		$confirm_password = $this->request->post("confirm_password");
		$user = User::findOrFail($this->user_id);
		if ($newpassword != $confirm_password) {
			$this->writeJson(0, '确认密码不一致');
		}
		$user->trade_password = $newpassword;
		$user->save();
		$this->writeJson();
	}
	
	function closeTradepwd()
	{
		$user = User::findOrFail($this->user_id);
		$user->trade_password = '';
		$user->save();
		$this->writeJson();
	}
	
	
	function getUserInfo()
	{
		$row = User::filter(function ($data) {
			$vip = Vip::find(1);
			$data->vip_price = $vip->price;
			
			
		})->find($this->user_id);
		if (!$row) {
			$this->writeJson(401, '请先登录');
		}
		$this->writeJson($row);
	}
	
	function getQRCode()
	{
		$client = new Client();
		$user = User::findOrFail($this->user_id);
		$access_token = Common::getWechatAccessToken();
		$wxacode = $client->post("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=$access_token", [
			'body' => json_encode([
				'page' => "pages/public/register",
				'scene' => "{$user->invitecode}",
				'check_path' => !env('APP_DEBUG'),
				'env_version' => env('APP_DEBUG', true) ? 'trial' : 'release'
			])
		]);
		$res = $wxacode->getBody()->getContents();
		$this->writeJson(['qrcode' => 'data:image/png;base64,' . base64_encode($res), 'user' => $user]);
	}
	
	function vipRenew()
	{
		$pay_type = $this->request->post('pay_type/d');
		$row = Vip::findOrFail(1);
		$user = User::findOrFail($this->user_id);
		if ($user->level == 1) {
			$this->writeJson(0, '请先成为会员');
		}
		$ordersn = Random::ordersn();
		$pay_amount = $row->price;
		// 启动事务
		Db::startTrans();
		try {
			VipOrders::create([
				'user_id' => $this->user_id,
				'vip_id' => $row->id,
				'pay_amount' => $pay_amount,
				'order_sn' => $ordersn,
				'mark' => '会员续费'
			]);
			$ret = Pay::pay($pay_type, $pay_amount, $ordersn, '会员续费', 'vip_renew', $user->openid);
			// 提交事务
			Db::commit();
		} catch (\Exception $e) {
			// 回滚事务
			Db::rollback();
			$this->writeJson(0, $e->getMessage());
		}
		$this->writeJson($ret);
	}
	
	#提现
	function withdraw()
	{
		$bank_id = $this->request->post('bank_id/d');
		$amount = $this->request->post('amount');
		$trade_password = $this->request->post('trade_password');
		$bank = UserBank::findOrFail($bank_id);
		$rate = Config::getFieldByName('withdraw_rate', 'value');
		$rate = $rate / 100;
		$fee = bcmul((string)$amount, (string)$rate, 2);
		if ($fee < 0.01) {
			$fee = 0.01;
		}
		$real_amount = bcsub($amount, (string)$fee, 2);
		$user = User::findOrFail($this->user_id);
		if ($user->vip_expiretime <= time()) {
			$this->writeJson(0, '请续费会员后再进行提现');
		}
		if ($user->trade_password != $trade_password) {
			$this->writeJson(0, '交易密码错误');
		}
		try {
			UserService::changeUserMoney(-$amount, $this->user_id, "提现-银行卡号" . substr($bank->account, -4));
			UserWithdraw::create([
				'user_id' => $this->user_id,
				'bank_id' => $bank->id,
				'amount' => $amount,
				'order_sn' => 'ZRKJ' . Random::ordersn(),
				'real_amount' => $real_amount,
				'name' => $bank->name,
				'idcard' => $bank->idcard,
				'account' => $bank->account,
				'bank' => $bank->bank,
				'bank_name' => $bank->bank_name,
				'mobile' => $bank->mobile,
				'fee' => $fee,
			]);
		} catch (\Exception $e) {
			$this->writeJson(0, $e->getMessage());
		}
		$this->writeJson();
	}
	
	#提现列表
	function withdrawList()
	{
		$rows = UserWithdraw::filter(function ($data) {
			$data->bank_text = $data->bank . '(' . substr($data->account, -4) . ')';
		})->where(['user_id' => $this->user_id])->order(['id' => 'desc'])->paginate()->items();
		$this->writeJson($rows);
	}
	
	
	function team()
	{
		$child = UserLayer::where(['pid' => $this->user_id, 'level' => 1])->select();
		$childids = array_column($child->toArray(), 'user_id');
		$childchildids = UserLayer::where(['pid' => $this->user_id, ['level', '<>', 1]])->column('user_id');
		$list = User::whereIn('id', $childids)->filter(function ($data) {
			$count = LineOrders::where(['user_id' => $data->id, 'status' => 4])->count();
			if ($count == 0) {
				$data->text = '已注册';
				$data->time_text = '注册时间：' . date('Y-m-d H:i:s', $data->jointime);
			} else {
				$order = LineOrders::where(['user_id' => $data->id, 'status' => 4])->find();
				$data->text = "已下{$count}单";
				$data->time_text = '首次下单时间：' . $order->createtime;
			}
		})->select();
		
		$childlist = User::whereIn('id', $childchildids)->filter(function ($data) {
			$count = LineOrders::where(['user_id' => $data->id, 'status' => 4])->count();
			if ($count == 0) {
				$data->text = '已注册';
				$data->time_text = '注册时间：' . date('Y-m-d H:i:s', $data->jointime);
			} else {
				$order = LineOrders::where(['user_id' => $data->id, 'status' => 4])->find();
				$data->text = "已下{$count}单";
				$data->time_text = '首次下单时间：' . $order->createtime;
			}
		})->select();
		
		$user = User::findOrFail($this->user_id);
		
		$this->writeJson(['list1' => $list, 'list2' => $childlist, 'count' => $child->count(), 'myparent' => $user->parent ? $user->parent->nickname : '无']);
	}
	
	/**
	 * 编辑个人信息
	 * @return void
	 */
	function userEdit()
	{
		$avatar = $this->request->post('avatar');
		$nickname = $this->request->post('nickname');
		$truename = $this->request->post('truename');
		$wechat = $this->request->post('wechat');
		$birthday = $this->request->post('birthday');
		$city = $this->request->post('city');
		$row = User::findOrFail($this->user_id);
		if (!empty($avatar)) {
			$row->avatar = $avatar;
		}
		if (!empty($nickname)) {
			$row->nickname = $nickname;
		}
		if (!empty($truename)) {
			$row->truename = $truename;
		}
		if (!empty($wechat)) {
			$row->wechat = $wechat;
		}
		if (!empty($city)) {
			$row->city = $city;
		}
		if (!empty($birthday)) {
			$row->birthday = $birthday;
		}
		$row->save();
		$this->writeJson();
	}
	
	
	#收益记录
	function userMoney()
	{
		$status = $this->request->get('status/d'); // 0全部 1支出 2收入
		$rows = UserMoneyLog::where(['user_id' => $this->user_id])->when(!empty($status), function (Query $query) use ($status) {
			if ($status == 1) {
				$query->where('money', '<=', 0);
			} else {
				$query->where('money', '>=', 0);
			}
		})->filter(function ($data) {
			if ($data->money > 0) {
				$data->money = '+' . $data->money;
			}
		})->order(['id' => 'desc'])->paginate()->items();
		$this->writeJson($rows);
	}
	
	#
	function changeMobile()
	{
		$mobile = $this->request->post('mobile');
		$captcha = $this->request->post('captcha');
		$captchaResult = \app\common\Sms::check($mobile, $captcha, 'changemobile');
		if (!$captchaResult) {
			$this->writeJson(0, '验证码错误');
		}
		$user = User::findOrFail($this->user_id);
		$user->mobile = $mobile;
		$user->save();
		$this->writeJson();
	}
	
	function collect()
	{
		$spot_ids = UserCollect::where(['user_id' => $this->user_id])->column('spot_id');
		$rows = LineSpot::withCount('assess')->filter(function ($data) {
			if ($data->score > 4) {
				$data->score_text = '很好';
			} elseif ($data->score > 3) {
				$data->score_text = '良好';
			} elseif ($data->score > 2) {
				$data->score_text = '一般';
			} else {
				$data->score_text = '差';
			}
		})->whereIn('id', $spot_ids)->paginate()->items();
		$this->writeJson($rows);
	}
	
	function coupon()
	{
		$status = $this->request->get('status/d'); // 1可使用 2已使用 3已失效
		$rows = UserCoupon::where(['user_id' => $this->user_id])->where(['status' => $status])->paginate()->items();
		$status1 = UserCoupon::where(['user_id' => $this->user_id])->where(['status' => 1])->count();
		$status2 = UserCoupon::where(['user_id' => $this->user_id])->where(['status' => 2])->count();
		$status3 = UserCoupon::where(['user_id' => $this->user_id])->where(['status' => 3])->count();
		$this->writeJson(['list' => $rows, 'status1' => $status1, 'status2' => $status2, 'status3' => $status3,]);
	}
	
	
	function refund()
	{
		$order_id = $this->request->post('order_id');
		$refund_order_sn = Random::ordersn();
		$row = LineOrders::findOrFail($order_id);
		try {
			if ($row->status != 6) {
				throw new \Exception('订单异常');
			}
			Pay::refund(1, $row->pay_amount, $row->order_sn, $refund_order_sn, '退押金');
		} catch (\Throwable $e) {
			$this->writeJson($e->getMessage());
		}
		$row->refund_order_sn = $refund_order_sn;
		$row->status = 7;
		$row->save();
		$this->writeJson();
	}
}
